package org.jfsm.demo.ccounter.cnt;

import org.jfsm.core.FSMHandler;
import org.jfsm.core.FSMOutput;
import org.jfsm.core.RetSignal;
import org.jfsm.demo.ccounter.CntController;
import org.jfsm.demo.ccounter.echo.EchoContext;
import org.jfsm.demo.ccounter.timer.TimerContext;

public class CntHandler extends FSMHandler<CntContext, CntRequest, FSMOutput, CntFSM> {

    private static final boolean USE_BARRIER = true;
    
    static TimerContext timerCtx;

    public CntHandler(CntFSM fsm) {
        super(fsm);
    }

    EH ehStart = new EH() {
        @Override
        public RetSignal handle(CntContext ctx) {

            timerCtx = fsm.timer.in.newContext();
            fsm.timer.in.init.dispatch(timerCtx);

            for (int i = 0; i < ctx.server.length; i++) {
                EchoContext cc = null;
                cc = fsm.echo.in.newContext();
                ctx.server[i] = cc;
                fsm.echo.in.init.dispatch(cc, ctx, null);
            }

            return in.reset;
        }
    };

    EH ehReset = new EH() {
        @Override
        public RetSignal handle(CntContext ctx) {
            ctx.starttime = System.nanoTime();
            ctx.msgCount = 0;
            for (int i = 0; i < ctx.counter.length; i++) {
                ctx.counter[i] = 0;
            }

            fsm.timer.in.start.dispatch(timerCtx, ctx, CntController.sampleTime);
            return in.sendPing;
        }
    };

    EH ehSendPing = new EH() {
        @Override
        public RetSignal handle(CntContext ctx) {
            for (int i = 0; i < ctx.server.length; i++) {
                ctx.counter[i]++;
                fsm.echo.in.ping.dispatch(ctx.server[i]);
            }
            return null;
        }
    };

    MH<Integer> mhPong = new MH<Integer>() {
        @Override
        public RetSignal handle(CntContext ctx, Integer msg) {
            ctx.msgCount++;

            if( USE_BARRIER ) {
                if (ctx.msgCount % ctx.server.length != 0) {
                    return null;
                }

                return in.sendPing;
            }
            else {
                fsm.echo.in.ping.dispatch( ctx.server[msg] );
                return null;
            }
        }
    };

    EH ehHold = new EH() {
        @Override
        public RetSignal handle(CntContext ctx) {
            ctx.display();
            fsm.timer.in.start.dispatch(timerCtx, ctx, CntController.holdTime);
            return null;
        }
    };

}
